package com.zl.websocket.config.websocket;

import java.security.Principal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

import com.zl.websocket.config.properties.GlobalProperties;
import com.zl.websocket.entity.UserInfo;
import com.zl.websocket.entity.WebsocketUser;
import com.zl.websocket.service.RouteService;
import com.zl.websocket.service.UserService;

/**
 * WebSocket STOMP Configuration
 * 
 * @author haycco
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

	@Autowired
	private GlobalProperties globalProperties;

	@Autowired
	@Qualifier("websocketRouteService")
	private RouteService websocketRouteService;
	
	@Autowired
	private UserService userService;

	@Override
	public void configureClientInboundChannel(ChannelRegistration registration) {
		registration.interceptors(new ChannelInterceptorAdapter() {
			@Override
			public Message<?> preSend(Message<?> message, MessageChannel channel) {
				StompHeaderAccessor headerAccessor = MessageHeaderAccessor.getAccessor(message,
						StompHeaderAccessor.class);
				if (StompCommand.CONNECT.equals(headerAccessor.getCommand())) {//建立连接
					String tokenKey = globalProperties.getWebsocket().getTokenKey();
					if(headerAccessor.containsNativeHeader(tokenKey)) {
						//把连接到的服务实例放到请求头
						headerAccessor.setHeader("SERVER-INSTANCE_ID", websocketRouteService.getInstanceId());
						String token = headerAccessor.getFirstNativeHeader(tokenKey).toString();
						UserInfo user = userService.getUserInfoByToken(token);
						if(null != user) {
							headerAccessor.setUser(new WebsocketUser(user));
							//缓存用户和channel关系
							websocketRouteService.userConnect(user.getId());
						}else {
							throw new RuntimeException("token有误");
						}
					}
				}else if(StompCommand.DISCONNECT.equals(headerAccessor.getCommand())) {//断开连接
					Principal user = headerAccessor.getUser();
					if(null != user) {
						websocketRouteService.userDisConnect(((WebsocketUser)user).getUser().getId());
					}
				}
				return message;
			}
		});
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.enableSimpleBroker("/topic/", "/queue/");
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/gs-websocket").setAllowedOrigins("*").withSockJS();
	}

}
